package cloud.tianai.mate.captcha.interceptor.impl;

import cloud.tianai.captcha.common.AnyMap;
import cloud.tianai.captcha.common.response.ApiResponse;
import cloud.tianai.captcha.common.response.CodeDefinition;
import cloud.tianai.captcha.common.util.CaptchaTypeClassifier;
import cloud.tianai.captcha.interceptor.Context;
import cloud.tianai.captcha.resource.common.model.dto.Resource;
import cloud.tianai.captcha.resource.impl.provider.ClassPathResourceProvider;
import cloud.tianai.captcha.validator.common.model.dto.ImageCaptchaTrack;
import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
import cloud.tianai.mate.captcha.validator.common.util.TrackUtils;
import cloud.tianai.neuron.common.Matrix;
import cloud.tianai.neuron.regression.LogisticRegression;
import lombok.SneakyThrows;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.List;

/**
 * @Author: 天爱有情
 * @date 2023/1/4 8:40
 * @Description 基于逻辑回归模型进行训练以及预测
 */
public class LRTrackCaptchaInterceptor implements CaptchaInterceptor {
    public static final CodeDefinition DEFINITION = new CodeDefinition(50002, "lr check fail");

    private LogisticRegression LR;

    @Override
    public String getName() {
        return "lr_check";
    }

    @SneakyThrows
    public LRTrackCaptchaInterceptor() {
        // 使用默认的模型
        Resource resource = new Resource("classpath", "META-INF/model/LR.model");
        InputStream inputStream = new ClassPathResourceProvider().getResourceInputStream(resource);
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        LR = (LogisticRegression) objectInputStream.readObject();
    }

    @SneakyThrows
    public LRTrackCaptchaInterceptor(InputStream model) {
        ObjectInputStream objectInputStream;
        if (model instanceof ObjectInputStream) {
            objectInputStream = (ObjectInputStream) model;
        } else {
            objectInputStream = new ObjectInputStream(model);
        }
        LR = (LogisticRegression) objectInputStream.readObject();
    }


    public LRTrackCaptchaInterceptor(LogisticRegression LR) {
        this.LR = LR;
    }


    @Override
    public ApiResponse<?> afterValid(Context context, String type, ImageCaptchaTrack imageCaptchaTrack, AnyMap validData, ApiResponse<?> basicValid) {
        if (!basicValid.isSuccess()) {
            return context.getGroup().afterValid(context, type, imageCaptchaTrack, validData, basicValid);
        }
        if (!CaptchaTypeClassifier.isSliderCaptcha(type)) {
            // 不是滑动验证码的话暂时跳过
            return ApiResponse.ofSuccess();
        }
        List<Double> features = context.getData(TrackFeaturesGenerator.TRACK_FEATURES_KEY, List.class);
        if (features == null) {
            features = TrackUtils.features(imageCaptchaTrack.getTrackList());
            context.putData(TrackFeaturesGenerator.TRACK_FEATURES_KEY, features);
        }
        // 先进行一下基本校验
        Double yMin = features.get(2);
        Double yMax = features.get(3);
        Double totalTime = features.get(4);
        Double yStd = features.get(10);
        Double tStd = features.get(12);
        if (yMin >= yMax || totalTime < 500 || yStd == 0 || tStd == 0) {
            context.end();
            return ApiResponse.ofMessage(DEFINITION);
        }

        Matrix matrix = new Matrix(0, 0);
        matrix.add(features);
        // 预测
        Double predict = LR.predict(matrix).get(0, 0);
        boolean check = predict > 0.5;
        if (check) {
            return ApiResponse.ofSuccess();
        }
        context.end();
        return ApiResponse.ofMessage(DEFINITION);
    }
}
